package com.da.javatest.util;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.da.javatest.annotation.DataMasking;
import com.da.javatest.enums.DataMaskingType;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.Objects;

/**
 * @author dsj
 */
@AllArgsConstructor
@NoArgsConstructor
public class DataMaskingSerialize extends JsonSerializer implements ContextualSerializer {

    private DataMaskingType type;

    private Integer start;

    private Integer end;

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value == null) {
            gen.writeNull();
        } else if (type == DataMaskingType.CUSTOM) {
            gen.writeString(CharSequenceUtil.hide((CharSequence)value, start, end));
        } else if (type != null) {
            gen.writeString(DesensitizedUtil.desensitized((CharSequence)value,
                DesensitizedUtil.DesensitizedType.valueOf(type.name())));
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
        throws JsonMappingException {
        if (Objects.nonNull(property)) {
            //判断是否为string类型
            if (Objects.equals(property.getType().getRawClass(), String.class)) {
                DataMasking anno = property.getAnnotation(DataMasking.class);
                if (Objects.isNull(anno)) {
                    anno = property.getContextAnnotation(DataMasking.class);
                }
                if (Objects.nonNull(anno)) {
                    return new DataMaskingSerialize(anno.type(), anno.start(), anno.end());
                }
            }
            return prov.findValueSerializer(property.getType(), property);
        }
        return prov.findNullValueSerializer(null);
    }
}
